import datetime

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator, MaxValueValidator
from django.utils import timezone
import re


def validate_min_length(value):
    if len(value) < 3:
        raise ValidationError('不能小于3个字符。')


# unique = True 唯一值
# blank = True 表示表单中的该字段可以不填（默认为False）
# null = True 表示该字段在数据库中可以为空
# db_index=True 创建索引
class Role(models.Model):
    """定义用户的角色"""
    role_name = models.CharField(max_length=50, unique=True,
                                 null=True, blank=True, verbose_name='角色名称')
    description = models.TextField(blank=True, null=True, verbose_name='角色描述')

    class Meta:
        db_table = 'sa_role'
        verbose_name = 'SA角色'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.role_name


# AbstractUser 包含以下字段：
# 核心字段：username、password、email、first_name、last_name。
# 权限和状态字段：is_staff、is_active、is_superuser。
# 时间戳字段：date_joined、last_login。
# 组和权限字段：groups、user_permissions。
class User(AbstractUser):
    """自定义用户模型类，继承AbstractUser"""
    mobile = models.CharField(verbose_name='手机号', max_length=11, unique=True, help_text='可以使用手机号登录')
    employee_num = models.CharField(verbose_name='员工号', max_length=12, unique=True,
                                    help_text='请录入：FBCN + XXXX 格式')
    cn_name = models.CharField(verbose_name='中文名', max_length=10,
                               db_index=True)
    en_name = models.CharField(verbose_name='英文名', max_length=18, blank=True, null=True)
    cse_num = models.CharField(verbose_name='CSE_No', max_length=128, blank=True, null=True)
    region = models.CharField(verbose_name='所属', max_length=4,
                              choices=(
                                  ('ERO', 'ERO-东区'),
                                  ('SRO', 'SRO-南区'),
                                  ('WRO', 'WRO-西区'),
                                  ('NRO', 'NRO-北区'),
                              ), default='ERO'
                              )
    city = models.CharField(verbose_name='城市', max_length=20, blank=True, null=True)
    roles = models.ManyToManyField(to=Role, blank=True, verbose_name='角色')

    class Meta:
        db_table = 'sa_user'  # 表名
        verbose_name = 'SA人员信息'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.cn_name


class Company(models.Model):
    """公司信息"""
    name = models.CharField(verbose_name='公司名称', max_length=128,
                            unique=True, db_index=True, help_text='请输入完整公司注册名称',
                            validators=[validate_min_length])
    # 层级关系
    parent_company = models.ForeignKey(
        'self',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name='母公司',
        db_index=True,
        related_name='subsidiaries',  # 通过 母公司.subsidiaries.all()获取所有子公司
    )
    region = models.CharField(
        verbose_name='区域',
        max_length=4,
        choices=(
            ('', '--请择区域--'),
            ('ERO', '东区 (ERO)'),
            ('SRO', '南区 (SRO)'),
            ('WRO', '西区 (WRO)'),
            ('NRO', '北区 (NRO)'),
        ), default='', blank=True
    )
    status = models.BooleanField(verbose_name='状态', default=True, help_text='激活/超出服务期')
    remark = models.TextField(verbose_name='备注', null=True, blank=True, default='', max_length=200)

    class Meta:
        db_table = 'company'
        verbose_name = '客户名称'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

    def clean(self):
        """
        验证公司层级关系：
        1. 不能设置自己为母公司
        2. 不能形成循环引用 避免 A→B→A 这样的循环关系
        3. 限制最多2层结构（即只有一级父子关系）
        """
        # 如果没有设置母公司，无需检查
        if not self.parent_company:
            return

        # 检查1：直接循环引用（自己作为自己的母公司）
        if self.parent_company.id == self.pk:
            raise ValidationError({
                'parent_company': '不能选择自己作为母公司！'
            })

        # 检查2：间接循环引用和层级深度
        current = self.parent_company
        depth = 0  # 从直接母公司开始计数（0=直接母公司，1=祖父公司）

        while current is not None:
            # 检查循环引用 （如 A→B→A）
            if current.id == self.id:
                raise ValidationError({
                    'parent_company': '检测到循环引用！不能成为自己的祖先！'
                })

            # 检查层级深度
            if depth >= 1:  # 如果已经有一级父公司
                raise ValidationError({
                    'parent_company': '公司层级过深，最多允许一级父子关系'
                })
            # 关键：移动指针, 对 current 重新赋值
            current = current.parent_company
            depth += 1


class CustomerInfo(models.Model):
    """ 客户信息 """
    name = models.CharField(verbose_name='客户名称',
                            max_length=128, unique=True, db_index=True,
                            validators=[validate_min_length],
                            help_text='请输入完整公司注册名称',
                            error_messages={
                                'unique': '该客户名称已存在于系统中'
                            })
    region = models.CharField(
        verbose_name='区域',
        max_length=4,
        choices=(
            ('', '--请择区域--'),
            ('ERO', '东区 (ERO)'),
            ('SRO', '南区 (SRO)'),
            ('WRO', '西区 (WRO)'),
            ('NRO', '北区 (NRO)'),
        ), default='', blank=True
    )
    remark = models.TextField(verbose_name='备注', null=True, blank=True,
                              default='', help_text='可以标记关联公司名, 实现与客户名称一起检索')
    status = models.BooleanField(verbose_name='激活', default=True, help_text='服务期内/服务过期')

    class Meta:
        db_table = 'customerinfo'
        verbose_name = '客户信息'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class Project(models.Model):
    """项目信息"""
    # 基础信息
    SR_No = models.CharField(verbose_name='SR_No#', unique=True, max_length=18,
                             help_text='项目编号唯一值')
    customer = models.ForeignKey(verbose_name='项目客户', to=CustomerInfo,
                                 on_delete=models.PROTECT, db_index=True)
    creator = models.ForeignKey(to=User, verbose_name='创建者',
                                on_delete=models.SET_DEFAULT, default=10, db_index=True)
    is_team_project = models.BooleanField(default=False, verbose_name='是否多人参与')
    participants = models.ManyToManyField(to=User, verbose_name='项目参与者', blank=True,
                                          related_name='participating_projects')
    # 分类信息
    CATEGORY_CHOICES = (
        ('故障排除', '故障排除'),
        ('新购实施', '新购实施'),
        ('添加设备', '添加设备'),
        ('添加模块', '添加模块'),
        ('变更需求', '变更需求'),
        ('升级版本', '升级版本'),
        ('系统迁移', '系统迁移'),
        ('系统变更', '系统变更'),
        ('技术咨询', '技术咨询'),
        ('应用开发', '应用开发'),
        ('项目管理', '项目管理'),
        ('色彩管理', '色彩管理'),
        ('其它', '其它'),
    )
    category = models.CharField(verbose_name='工作分类', choices=CATEGORY_CHOICES,
                                max_length=20, default='故障排除')
    SOFTWARE_CHOICES = (
        (None, '-- 请选择产品 --'),
        ('awms_entry', 'AWMS Entry'),
        ('awms_option', 'AWMS Option'),
        ('awms_enterprise', 'AWMS Enterprise'),
        ('siyin', '司印'),
        ('changyin', '畅印'),
        ('amdp', 'AMDP'),
        ('equitrac', 'Equitrac'),
        ('sharescan', 'eCopy ShareScan'),
        ('papercut', 'PaperCut'),
        ('atg_face', 'ATG Face'),
        ('sdcc_custom', 'SDCC定制'),
        ('other', '其他产品'),
    )
    software = models.CharField(verbose_name='使用方案', max_length=30,
                                choices=SOFTWARE_CHOICES, null=True, blank=True)
    version = models.CharField(verbose_name='软件版本', max_length=10,
                               null=True, blank=True)
    level = models.CharField(verbose_name='故障等级', max_length=20,
                             null=True, blank=True, choices=(
            ('L1', 'L1（业务全阻）'),
            ('L2', 'L2（核心功能不可用)'),
            ('L3', 'L3（部分功能影响）'),
            ('L4', 'L4（轻微影响）'),
        ))
    # 资源统计
    server_num = models.PositiveSmallIntegerField(
        verbose_name='服务器数量', default=0,
        validators=[
            MinValueValidator(0, message="数量不能小于0"),
            MaxValueValidator(1000, message="超过最大允许数量(1000)")
        ])
    mfd_num = models.PositiveSmallIntegerField(
        verbose_name='MFD数量', default=0,
        validators=[
            MinValueValidator(0, message="数量不能小于0"),
            MaxValueValidator(10000, message="超过最大允许数量(10000)")
        ])
    printer_num = models.PositiveSmallIntegerField(
        verbose_name='打印机数量', default=0,
        validators=[
            MinValueValidator(0, message="数量不能小于0"),
            MaxValueValidator(10000, message="超过最大允许数量(10000)")
        ])
    # 时间与状态
    start_date = models.DateField(verbose_name='开始日期',
                                  null=True,
                                  blank=True, db_index=True)
    status = models.CharField(verbose_name='项目阶段', choices=(
        ('Ongoing', '进行中'),
        ('Completed', '已完成'),
    ), max_length=20, default='Ongoing')
    end_date = models.DateField(verbose_name='结束日期',
                                null=True,
                                blank=True, db_index=True)
    duration = models.IntegerField(verbose_name="合计天数", null=True, blank=True,
                                   help_text="根据开始/结束日期自动计算")
    big_project = models.BooleanField(verbose_name='大项目', default=False)
    contract_amount = models.PositiveIntegerField(
        verbose_name='合同金额（K）', default=0,
        validators=[
            MinValueValidator(0, message="金额不能为负")
        ])
    description = models.TextField(verbose_name='项目描述')
    points = models.DecimalField(
        verbose_name='得分', max_digits=6,
        decimal_places=2, blank=True, default=0.00,
        validators=[
            MinValueValidator(0, message="得分不能为负值"),
            MaxValueValidator(9999.99, message="得分超过系统上限")
        ], help_text="项目得分（保留两位小数）")

    class Meta:
        db_table = 'project'
        verbose_name = '项目信息'
        verbose_name_plural = verbose_name

    def __str__(self):
        return f"{self.creator} - {self.customer}"


class Activity(models.Model):
    """ Activity信息 """
    project = models.ForeignKey(
        verbose_name='所属项目', to=Project,
        on_delete=models.PROTECT)
    creator = models.ForeignKey(verbose_name='作者', to=User,
                                on_delete=models.PROTECT)
    # 后端计算，Project 的 SR_No + .1, 非显性
    activity_number = models.CharField(
        verbose_name='Activity_No#', unique=True,
        max_length=20, blank=True, null=True)
    type_choice = (
        ('故障排除', '故障排除'),
        ('新购实施', '新购实施'),
        ('添加设备', '添加设备'),
        ('添加模块', '添加模块'),
        ('变更需求', '变更需求'),
        ('升级版本', '升级版本'),
        ('系统迁移', '系统迁移'),
        ('系统变更', '系统变更'),
        ('技术咨询', '技术咨询'),
        ('应用开发', '应用开发'),
        ('项目管理', '项目管理'),
        ('色彩管理', '色彩管理'),
        ('其它', '其它'),
    )
    activity_type = models.CharField(
        verbose_name='任务类型',
        choices=type_choice, max_length=20, default='故障排除')
    activity_date = models.DateField(verbose_name='任务日期', null=True, blank=True)
    start_time = models.TimeField(verbose_name='开始时间', null=True, blank=True)
    end_time = models.TimeField(verbose_name='结束时间', null=True, blank=True)
    # 计算, 非显性
    total_time = models.PositiveIntegerField(
        verbose_name='工作总时间（分钟）', blank=True, default=0)
    is_overtime = models.BooleanField(verbose_name='加班', default=False)
    overtime = models.PositiveSmallIntegerField(
        verbose_name='加班时间(分钟)', blank=True, default=0)
    task_server_num = models.PositiveSmallIntegerField(
        verbose_name='服务器数量', default=0)
    task_mfd_num = models.PositiveSmallIntegerField(
        verbose_name='MFD数量', default=0)
    task_printer_num = models.PositiveSmallIntegerField(
        verbose_name='打印机数量', default=0)
    # 取 project的software， 非显性
    software_type = models.CharField(
        verbose_name='软件类型', max_length=20, blank=True, null=True)
    description = models.TextField(verbose_name='工作内容记录')
    # 非显性
    points = models.DecimalField(
        verbose_name='得分', max_digits=6,
        decimal_places=2, blank=True, default=0.00,
        validators=[
            MinValueValidator(0, message="得分不能为负值"),
            MaxValueValidator(9999.99, message="得分超过系统上限")
        ], help_text="activity得分（保留两位小数）")

    class Meta:
        db_table = 'Activity'
        verbose_name = 'activity信息'
        verbose_name_plural = verbose_name

    def __str__(self):
        project_name = getattr(self.project, 'SR_No', '无项目')
        creator_name = getattr(self.creator, 'cn_name', '无creator')
        return f"选中的Activity [{self.id}]: 项目编号：[{project_name}], 作者：[{creator_name}]"


"""
知识共享平台模型设计
ProductType: 产品类型
KnowledgeDomain: 知识领域，网络，脚本，数据库
Article： 文章主体
Comment：评论
"""


class ProductType(models.Model):
    """Article涉及的产品类型"""
    name = models.CharField(max_length=50, verbose_name='类型名称', unique=True)
    description = models.TextField(blank=True, null=True, verbose_name='描述')

    class Meta:
        db_table = 'ProductType'
        verbose_name = '产品类型'
        verbose_name_plural = '产品类型'

    def __str__(self):
        return self.name


class KnowledgeDomain(models.Model):
    """文章标签"""
    name = models.CharField(max_length=50, verbose_name='领域名称', unique=True)
    color = models.CharField(max_length=20, verbose_name='颜色',
                             blank=True, default='#3498db')

    class Meta:
        db_table = 'KnowledgeDomain'
        verbose_name = '知识领域'
        verbose_name_plural = '知识领域'

    def __str__(self):
        return self.name


class Article(models.Model):
    """文章主体"""
    title = models.CharField(max_length=200, verbose_name='标题')
    author = models.ForeignKey(to=User, on_delete=models.SET_NULL, null=True,
                               verbose_name='作者', db_index=True)
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    category = models.ManyToManyField(to=ProductType, verbose_name='涉及产品',
                                      blank=True)
    tags = models.ManyToManyField(to=KnowledgeDomain, verbose_name='知识领域',
                                  blank=True)
    views = models.PositiveIntegerField(default=0, verbose_name='浏览量',
                                        blank=True)
    content = models.TextField(verbose_name="内容")

    # 只支持单个附件
    # attachments = models.FileField(verbose_name='附件', blank=True, null=True,
    #                                upload_to='attachments/%Y/%m/%d/',
    #                                editable=False,
    #                                help_text='弃用字段!')

    class Meta:
        db_table = 'Article'
        verbose_name = '知识文档'
        verbose_name_plural = '知识文档'

    def __str__(self):
        return self.title


class ArticleAttachment(models.Model):
    """ 文章附件 """
    article = models.ForeignKey(to=Article,
                                on_delete=models.CASCADE,  # 文章删除时附件级联删除
                                related_name='attachments',  # 反向查询名称
                                verbose_name='所属文章', db_index=True)
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='上传时间')
    file = models.FileField(verbose_name='附件', blank=True, null=True,
                            upload_to='attachments/%Y/%m%d/')

    class Meta:
        db_table = 'ArticleAttachment'
        verbose_name = '文章附件'
        verbose_name_plural = '文章附件'


"""
安装MPTT
pip install django-mptt

然后在你的 settings.py 中添加 mptt 到 INSTALLED_APPS：
INSTALLED_APPS = [
    # ...
    'mptt',
    # ...
]

class Comment(MPTTModel):
    parent = TreeForeignKey('self', null=True, blank=True, 
                           on_delete=models.CASCADE)
"""


class Comment(models.Model):
    """文章评论"""
    article = models.ForeignKey(Article, on_delete=models.CASCADE,
                                related_name='comments',
                                verbose_name='关联文章')
    author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='评论作者')
    content = models.TextField(max_length=1000, verbose_name='评论内容')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='评论时间')
    parent = models.ForeignKey('self', null=True, blank=True,
                               on_delete=models.CASCADE, verbose_name='父评论')
    depth = models.PositiveIntegerField(default=0, verbose_name='评论层级')

    class Meta:
        db_table = 'Comment'
        verbose_name = '评论'
        verbose_name_plural = '评论'
        ordering = ['-created_at']

    def __str__(self):
        return f"{self.author.cn_name} 对 《{self.article.title}》的评论"
